#pragma executioncharacterset("utf-8")
#include "disksizetable.h"
#include <QTableView>
#include <QTableWidgetItem>
#include <QHeaderView>
#include <QTimer>
#include <QFileInfo>
#include <QDir>
#include <QLatin1String>
#include <QProgressBar>
#ifdef Q_OS_WIN
#include "windows.h"
#endif

#define KB  (1024)
#define MB  (1024 * 1024)
#define GB  (1024 * 1024 *1024)

DiskSizeTable::DiskSizeTable(QWidget *parent)
{
    bgColor = QColor(255, 255, 255);
//    bgColor = QColor(0, 255, 255);
    pgrColor1 = QColor(24, 189, 155);
    pgrColor2 = QColor(255, 107, 107);

    textColor1 = QColor(10, 10, 10);
    textColor2 = QColor(255, 255, 255);
    textColor3 = QColor(255, 255, 255);

    process = new QProcess(this);
    connect(process, SIGNAL(readyRead()), this, SLOT(readData()));

    this->clear();

    this->setColumnCount(5);
    this->setColumnWidth(0, 50);
    this->setColumnWidth(1, 120);
    this->setColumnWidth(2, 120);
    this->setColumnWidth(3, 120);
    this->setColumnWidth(4, 120);

    this->setStyleSheet("QTableWidget::item{padding:0px}");

    QStringList headText;
    headText << "Disk" << "Used" << "Unused" << "Total" << "Used Percent";

    this->setHorizontalHeaderLabels(headText);
    this->setSelectionBehavior(QAbstractItemView::SelectRows);
    this->setEditTriggers(QAbstractItemView::NoEditTriggers);
    this->setSelectionMode(QAbstractItemView::SingleSelection);
    this->verticalHeader()->setVisible(true);
    this->horizontalHeader()->setStretchLastSection(true);

    QTimer::singleShot(0, this, SLOT(loadData()));
}

QColor DiskSizeTable::getBgColor()
{
    return bgColor;
}

QColor DiskSizeTable::getPgrColor1()
{
    return pgrColor1;
}

QColor DiskSizeTable::getPgrColor2()
{
    return pgrColor2;
}

QColor DiskSizeTable::getPgrColor3()
{
    return pgrColor3;
}

QColor DiskSizeTable::getTextColor1()
{
    return textColor1;
}

QColor DiskSizeTable::getTextColor2()
{
    return textColor2;
}

QColor DiskSizeTable::getTextColor3()
{
    return textColor3;
}

QSize DiskSizeTable::sizeHint()
{
    return QSize(500, 300);
}

QSize DiskSizeTable::minimumSizeHint()
{
    return QSize(200, 150);
}

void DiskSizeTable::loadData()
{
    int row = this->rowCount();
    for (size_t i = 0; i < row; i++) {
        this->removeRow(0);
    }

#ifdef Q_OS_WIN
    QFileInfoList list = QDir::drives();

    foreach (QFileInfo dir, list) {
        QString dirName = dir.absolutePath();
        LPCWSTR lpcwstrDriver = (LPCWSTR)dirName.utf16();
        ULARGE_INTEGER liFreeBytesAvailable, liTotalBytes, liTotalFreeBytes;

        if (GetDiskFreeSpaceEx(lpcwstrDriver, &liFreeBytesAvailable, &liTotalBytes, &liTotalFreeBytes)) {
            QString use = QString::number((double)(liTotalBytes.QuadPart - liTotalFreeBytes.QuadPart) / GB, 'f', 1);
            use += "G";
            QString free = QString::number((double)liTotalFreeBytes.QuadPart / GB, 'f', 1);
            free += "G";
            QString all = QString::number((double)liTotalBytes.QuadPart / GB, 'f', 1);
            all += "G";
            int percent = 100 - ((double)liTotalFreeBytes.QuadPart / liTotalBytes.QuadPart) * 100;

            insertSize(dirName, use, free, all, percent);
        }
    }
#else
    process->start("df -h");

#endif
}

void DiskSizeTable::setBgColor(const QColor &color)
{
    if (this->bgColor != color) {
        this->bgColor = color;
        this->loadData();
    }
}

void DiskSizeTable::setPgrColor1(const QColor &color)
{
    if (this->pgrColor1 != color) {
        this->pgrColor1 = color;
        this->loadData();
    }
}

void DiskSizeTable::setPgrColor2(const QColor &color)
{
    if (this->pgrColor2 != color) {
        this->pgrColor2 = color;
        this->loadData();
    }
}

void DiskSizeTable::setPgrCOlor3(const QColor &color)
{
    if (this->pgrColor3 != color) {
        this->pgrColor3 = color;
        this->loadData();
    }
}

void DiskSizeTable::setTextColor1(const QColor &color)
{
    if (this->textColor1 != color) {
        this->textColor1 = color;
        this->loadData();
    }
}

void DiskSizeTable::setTextColor2(const QColor &color)
{
    if (this->textColor2 != color) {
        this->textColor2 = color;
        this->loadData();
    }
}

void DiskSizeTable::setTextColor3(const QColor &color)
{
    if (this->textColor3 != color) {
        this->textColor3 = color;
        this->loadData();
    }
}

void DiskSizeTable::readData()
{
    while (!process->atEnd()) {
        QString result = QLatin1String(process->readLine());
#ifdef __arm__
        if (result.startsWith("/dev/root")) {
            checkSize(result, "Local Storage");
        }
        else if (result.startsWith("/dev/mmcblk")) {
            checkSize(result, "Local Storage");
        }
        else if (result.startsWith("/dev/mmcblk1p")) {
            checkSize(result, "SD");
            QStringList list = result.split(" ");
            emit sdDiskReceive(list.at(0));
        }
        else if (result.startsWith("/dev/sd")) {
            checkSize(result, "U Disk");
            QStringList list = result.split(" ");
            emit uDiskReceive(list.at(0));
        }
#endif
    }
}

void DiskSizeTable::checkSize(const QString &result, const QString &name)
{
    QString dev, use, free, all;
    int percent = 0;
    QStringList list = result.split(" ");
    int index = 0;

    for (int i = 0; i < list.count(); i++) {
        QString s = list.at(i).trimmed();

        if (s == "") {
            continue;
        }

        index++;

        if (index == 1) {
            dev = s;
        }
        else if (index == 2) {
            all = s;
        }
        else if (index == 3) {
            use = s;
        }
        else if (index == 4) {
            free = s;
        }
        else if (index == 5) {
            percent = s.left(s.length() - 1).toInt();
            break;
        }
    }

    if (name.length() > 0) {
        dev = name;
    }

    insertSize(dev, use, free, all, percent);
}

void DiskSizeTable::insertSize(const QString &name, const QString &use, const QString &free, const QString &all, int percent)
{
    int row = this->rowCount();
    this->insertRow(row);

    QTableWidgetItem* itemname = new QTableWidgetItem(name);
    QTableWidgetItem* itemuse = new QTableWidgetItem(use);
    itemuse->setTextAlignment(Qt::AlignCenter);
    QTableWidgetItem* itemfree = new QTableWidgetItem(free);
    itemfree->setTextAlignment(Qt::AlignCenter);
    QTableWidgetItem* itemall = new QTableWidgetItem(all);
    itemall->setTextAlignment(Qt::AlignCenter);

    this->setItem(row, 0, itemname);
    this->setItem(row, 1, itemuse);
    this->setItem(row, 2, itemfree);
    this->setItem(row, 3, itemall);

    QProgressBar* bar = new QProgressBar;
    bar->setRange(0, 100);
    bar->setValue(percent);

    QString qss = QString("QProgressBar{background:%1;border-width:0px;border-radius:0px;text-align:center;}"
                          "QProgress::chunk{border-radius:0px;}").arg(bgColor.name());

    if (percent < 50) {
        qss += QString("QProgressBar{color:%1;}QProgressBar::chunk{background:%2;}").arg(textColor1.name()).arg(pgrColor1.name());
    }
    else if (percent < 90) {
        qss += QString("QProgressBar{color:%1;}QProgressBar::chunk{background:%2;}").arg(textColor2.name()).arg(pgrColor2.name());
    }
    else {
        qss += QString("QProgressBar{color:%1;}QProgressBar::chunk{background:%2;}").arg(textColor3.name()).arg(pgrColor3.name());
    }

    bar->setStyleSheet(qss);
    this->setCellWidget(row, 4, bar);
}
